import sys, os, ConfigParser,time
try:
    import web
except ImportError:
    print "The Python module 'web' is required"
    sys.exit()
from web import form
import crisprsearch


#read crisprsearch.ini
config = ConfigParser.SafeConfigParser()
config.readfp(open('crisprsearch.ini'))


#Email settings
web.config.smtp_username = config.get('mail','username')
web.config.smtp_password = config.get('mail','password')
web.config.smtp_server = config.get('mail','server')
web.config.smtp_port = config.get('mail','port')
web.config.smtp_starttls = config.get('mail','tls')


#initialize web stuff and check user specified settings
urls = (
    '/', 'index',
    '/reset', 'Reset',
    '/search', 'Search',
)
web.config.debug = False
app = web.application(urls, globals())
session = web.session.Session(app, web.session.DiskStore('sessions'))
web.config.session_parameters.regenerate_id=False
render = web.template.render('templates/')


#initialize other stuff
baseUrl = config.get('misc','base_url')
genomes = []
ucscVars = {}
for key,name in config.items('ref_genomes'):
    genomes.append((name.split('|')[0],key))
    try:
        ucscVars[name.split('|')[0]] = name.split('|')[1].split(',')
    except:
        ucscVars[name.split('|')[0]] = ['','','']
                                     
try:
    port = config.getint('misc','port')
except ValueError:
    print 'Specified port must be an integer.'
    sys.exit()
    
if os.path.isdir(config.get('misc','ref_genome_dir')) is not True:
    print "Bowtie reference genome dir is not present at specified location."
    sys.exit()
else:
    genomePath = config.get('misc','ref_genome_dir')


#Checks validity of inputs
vfaPaste = form.regexp(r"($^)|(^>.*\n[actgACTG]{20})", '<span class=r>Must be a DNA sequence in the FASTA format.</span>')
vfaUpload = form.Validator("<span class=r>Select a file.</span>", lambda x: len(x)>0)
vrule = form.regexp(r"[ATCGatcgBbNn]{3,50}$", '<span class=r>Must be a valid rule between 3 and 50 characters</span>')
vhamming = form.Validator('<span class=r>Must be an integer, 0-3 inclusive</span>', lambda x: 0<=int(x)<=3)
vseed = form.Validator('<span class=r>Must be an integer, 0 or 5-23 inclusive</span>', lambda x: 4<int(x)<50 or int(x)==0)
vname = form.regexp(r".{1,}$", "<span class=r>Please enter a job name</span>")
vemail = form.regexp(r"($^)|(.*@.*\..{2,10})", "<span class=r>Please enter a valid email address</span>")



#Creates the input form
form1 = form.Form(
    form.Textarea('faPaste',vfaPaste,post='<br><span>or</span>', rows=10, cols=60,description='FASTA formatted sequence',class_='input_form'),
    form.File('faUpload',description='FASTA file',class_='input_form'),
    form.Dropdown('refGenome',genomes,description=' Reference genome',class_='input_form'),
    form.Textbox('rule',vrule,size=40,maxlength=50,value='BBBBBBBBBBBBBBBBBNGG',description='Rule',class_='input_form'),
    form.Textbox('hamming',vhamming,size=40, maxlength=1, value=0,description='Max no. of mismatches in 3\' region of rule',class_='input_form'),
    form.Textbox('seed',vseed,size=40,maxlength=2, value=0,description='Length of 3\' region of rule',class_='input_form'),
    form.Textbox('jobName',vname, size=40,description='Job name',class_='input_form'),
    form.Textbox('email',vemail, size=40,description='Email address',class_='input_form'),
    form.Button('Search', id="submit"),
)



class index:
    def GET(self):
        f1 = form1()
        #Create 'session.current' if non-existant (i.e. users first visit).
        try:
            return render.index(session.current,f1)
        except AttributeError:
            raise web.seeother('reset')
        
    def POST(self):
        f1 = form1()
        if not f1.validates():
            return render.index(session.current,f1)
        else:
            x = web.input(faUpload={})

            #Create directories
            path = ('static/{}/'.format( time.strftime('%H%M%S') ))
            os.mkdir(path)
            os.mkdir('{}json/'.format(path))
            os.mkdir('{}output/'.format(path))

            #Create FASTA file from input sequence
            faPath = '{}uploaded.fa'.format(path)
            fas = open(faPath,'w')
            if x.faUpload.filename is '':
                fas.write(f1.d.faPaste)
            else:
                fas.write(x.faUpload.value)
            if fas.tell() == 0:
                return 'No FASTA file specified or sequence entered.'
            #if crisprsearch.checkFastaFil() == 0:
            #    return 'Incorrect FASTA file'
            fas.close()
                   

            #Do the CRISPR!
            whereabouts = crisprsearch.findCandidateSequenceLocation(faPath,genomePath+f1.d.refGenome)
            candidateTargets = crisprsearch.findCandidateTargets(
                f1.d.rule,faPath)
            potentialOffTargets = crisprsearch.createPotentialOffTargetStrings(
                f1.d.rule, candidateTargets)
            offTargSummary,actualOffTargets = crisprsearch.predictPotentialOffTargets(
                candidateTargets, potentialOffTargets, os.path.join(genomePath+f1.d.refGenome), f1.d.hamming, int(f1.d.seed),f1.d.rule,whereabouts,path)
            crisprsearch.createOutputFiles(
                candidateTargets, actualOffTargets, offTargSummary, f1.d.rule, int(f1.d.hamming), int(f1.d.seed), whereabouts, f1.d.jobName,ucscVars[f1.d.refGenome], path)
            try:
                web.sendmail('search@crispr.com', f1.d.email, 'CRISPR-search results',
                             'Click <a href=\'http://{}:{}/{}\'>here</a> to view your results.'.format(baseUrl,port,path),
                             headers={'Content-Type':'text/html;charset=utf-8'}
                )
            except:
                print 'Email settings are wrong...\n'
                
            #Add link to search for current session
            session.current += '<li class=\'recent\'><a href = {}>{}</a>\n'.format(path,f1.d.jobName)
            raise web.seeother(path)


class Reset:
    def GET(self):
        session.current = ''
        raise web.seeother('/')

class Search:
        def GET(self):
            return('testt')
		
		
if __name__ == '__main__':
    web.httpserver.runsimple(app.wsgifunc(), ("0.0.0.0", port))
